package com.cqc.manage.token;

import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.cqc.manage.dto.PayloadDto;
import com.cqc.manage.entity.User;
import com.cqc.manage.error.tokenerror.ErrorTokenException;
import com.cqc.manage.error.tokenerror.ExpiredTokenException;
import com.nimbusds.jose.*;


import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.Date;
import java.util.UUID;

/**
 * JWT Token实现类
 */
@Service
public class JwtTokenServiceImpl implements JwtTokenService {

    @Value("jwt.secret")
    private String secret;
    @Value("jwt.theme")
    private String theme;

    /**
     * 生成token
     * @param payloadStr
     * @return
     * @throws JOSEException
     */
    @Override
    public String generateTokenByHMAC(String payloadStr) throws JOSEException {
        // 创建JWT头，设置签名算法和类型
        JWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.HS256).
                type(JOSEObjectType.JWT)
                .build();
        //将负载信息封装到Payload中
        Payload payload = new Payload(payloadStr);
        //创建JWS对象
        JWSObject jwsObject = new JWSObject(jwsHeader, payload);
        //创建HMAC签名器
        JWSSigner jwsSigner = new MACSigner(SecureUtil.md5(secret));
        //签名
        jwsObject.sign(jwsSigner);
        return jwsObject.serialize();
    }

    /**
     * 验证token
     * @param token
     * @return
     * @throws ParseException
     * @throws JOSEException
     */
    @Override
    public PayloadDto verifyTokenByHMAC(String token) throws ParseException,JOSEException {
        // 从token中解析JWT对象
        JWSObject jwsObject = JWSObject.parse(token);
        // 创建HMAC验证器
        JWSVerifier jwsVerifier = new MACVerifier(SecureUtil.md5(secret));
        if (!jwsObject.verify(jwsVerifier)){
            throw new ErrorTokenException("token签名不合法");
        }
        String payload = jwsObject.getPayload().toString();
        PayloadDto payloadDto = JSONUtil.toBean(payload, PayloadDto.class);
        if (payloadDto.getExpirationTime() < new Date().getTime()){
            throw new ExpiredTokenException();
        }
        return payloadDto;
    }

    /**
     * 设置JWT token的默认DTO
     * @return
     */
    @Override
    public PayloadDto getDefaultPayloadDto(User user) {
        Date now = new Date();
//        DateTime exp = DateUtil.offsetSecond(now, 10);
        Date exp = DateUtil.offsetWeek(now,1);
        return PayloadDto.builder()
                .theme(theme)
                .timeFiled(now.getTime())
                .expirationTime(exp.getTime())
                .jwtId(UUID.randomUUID().toString())
                .userName(user.getUserAccount()).build();
    }
}
